package com.cbh.amadeus.common.handler;

import com.cbh.amadeus.common.enums.MessageType;
import com.cbh.amadeus.common.protocol.AmadeusMessageProtocol;
import com.cbh.amadeus.common.protocol.AmadeusMessageWrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author ChenBiHui
 * @date 2025/4/25
 */
@Slf4j
public class HeartBitHandler extends SimpleChannelInboundHandler<AmadeusMessageWrap> {

    private final AtomicInteger bitCount = new AtomicInteger(0);
    private final boolean readerIdle;
    private final boolean writerIdle;

    public HeartBitHandler(boolean readerIdle, boolean writerIdle) {
        this.readerIdle = readerIdle;
        this.writerIdle = writerIdle;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, AmadeusMessageWrap msg) {
        bitCount.set(0);
        MessageType type = MessageType.find(msg.getType());
        if (type == MessageType.BIT_SEND) {
            ctx.writeAndFlush(bitBack());
            return;
        }
        if (type == MessageType.BIT_BACK) {
            return;
        }
        ctx.fireChannelRead(msg);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent trans = (IdleStateEvent) evt;
            IdleState state = trans.state();
            if (state == null) {
                return;
            }
            switch (state) {
                case READER_IDLE:
                    if (!readerIdle) {
                        break;
                    }
                    if (bitCount.get() <= 3) {
                        bitCount.incrementAndGet();
                        break;
                    }
                    Channel channel = ctx.channel();
                    channel.close();
                    break;
                case WRITER_IDLE:
                    if (!writerIdle) {
                        break;
                    }
                    ctx.writeAndFlush(bitSend());
                    break;
                default:
                    break;
            }
        }
        super.userEventTriggered(ctx, evt);
    }

    private AmadeusMessageWrap bitSend() {
        AmadeusMessageWrap wrap = new AmadeusMessageWrap();
        wrap.setMagic(AmadeusMessageProtocol.MAGIC);
        wrap.setType((MessageType.BIT_SEND.getType().byteValue()));
        return wrap;
    }

    private AmadeusMessageWrap bitBack() {
        AmadeusMessageWrap wrap = new AmadeusMessageWrap();
        wrap.setMagic(AmadeusMessageProtocol.MAGIC);
        wrap.setType((MessageType.BIT_BACK.getType().byteValue()));
        return wrap;
    }
}
